package com.mt.roll.opcua.opcua.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author: 蔡翔
 * @Date: 2019/10/12 15:15
 * @Version 1.0
 */
@RestController
@RequestMapping("/testPLC1")
public class WmcController {
/*


    private static final Logger logger = LoggerFactory.getLogger(WmcController.class);
    @Autowired
    UAService uaService;

    @Autowired
    WebSocketServer webSocketServer;

    */
/**
     * 测试real 类型（get / set）
     **//*

    @PostMapping("/noRR")
    public R noRr() throws Exception {
        return R.ok().put("OK",123);
    }

    @GetMapping("/norr")
    public R removeThisPlc() throws Exception {
        uaService.dynamicRemovePlc("plc1");
        return R.ok();
    }


    @GetMapping("testWriteOneVar")
    public R testWriteOneVar(Integer a) throws Exception {
        System.out.println("uaService.hashCode(): "+uaService.hashCode());
        Boolean aBoolean = null;
        try {
            aBoolean = uaService.setValue(PLCVar.INT32_3, a,"plc1");
        }catch (Exception e){
            String[] errMsgs = e.getMessage().split(",");
            for(String i : errMsgs){
                System.out.println("i = 》 " + i);
            }
            System.err.println("err msg: "+uaService.extractError(e.getMessage()));
        }

        return R.ok().put("result",aBoolean);
    }
    @GetMapping("testWriteOneVarForByte")
    public R testWriteOneVarForByte(Integer a) throws Exception {
        System.out.println("uaService.hashCode(): "+uaService.hashCode());
        Boolean aBoolean = null;
        try {
            aBoolean = uaService.setValue(PLCVar.BYTE_3, Unsigned.ubyte(a),"plc1");
        }catch (Exception e){
            String[] errMsgs = e.getMessage().split(",");
            for(String i : errMsgs){
                System.out.println("i = 》 " + i);
            }
            System.err.println("err msg: "+uaService.extractError(e.getMessage()));
        }

        return R.ok().put("result",aBoolean);
    }


    @GetMapping("testHistoryRead")
    public R testHistoryRead() throws Exception {
        System.out.println("uaService.hashCode(): "+uaService.hashCode());

        DateTime start = new DateTime(new Date(System.currentTimeMillis()+10000));
        DateTime end = new DateTime(new Date());

        DateTime start1 = DateTime.MIN_VALUE;
        DateTime end1 = DateTime.now();

        List<DataValue> aBoolean = uaService.historyRead("plc1",start,end,5,"Counter1");
        return R.ok().put("result",aBoolean);
    }

    @GetMapping("testReadStringArray")
    public R testReadStringArray() throws Exception {
        System.out.println("uaService.hashCode(): "+uaService.hashCode());

        DataValue aBoolean = uaService.getValue(PLCVar.StringArray_3,"plc1");
        List<String> s = (List<String>)aBoolean.getValue().getValue();
        return R.ok().put("result",aBoolean.getValue().getValue());
    }

    @GetMapping("testReadBooleanArray")
    public R testReadBooleanArray() throws Exception {
        System.out.println("uaService.hashCode(): "+uaService.hashCode());
        DataValue aBoolean = null;
        try {
            aBoolean = uaService.getValue(PLCVar.BooleanArray_3,"plc1");
        }catch (Exception e){
            String[] errMsgs = e.getMessage().split(",");
            for(String i : errMsgs){
                System.out.println("i = 》 " + i);
            }

            System.err.println("err msg: "+uaService.extractError(e.getMessage()));
            if("Bad_ConnectionRejected".equals(uaService.extractError(e.getMessage()))){
                System.err.println("OPC SERVER 已经宕机 请确认开启");
            }
        }
        System.out.println(aBoolean.getValue().getValue().getClass().isArray());
        return R.ok().put("result",aBoolean.getValue().getValue());
    }

    @GetMapping("testWriteTwoVar")
    public R testWriteTwoVar(Boolean b,Integer a) throws Exception {
        System.out.println("uaService.hashCode(): "+uaService.hashCode());

        List<PLCVar> list = new ArrayList<>();
        list.add(PLCVar.INT32_3);
        list.add(PLCVar.Boolean_3);

        List<Object> value = new ArrayList<>();
        value.add(a);
        value.add(b);

        Boolean aBoolean = uaService.setValues(list, value,"plc1");
        return R.ok().put("result",aBoolean);

    }

    @GetMapping("getUniqueId")
    public R getUniqueId(){
        return R.ok(webSocketServer.getUniqeId());
    }

    @GetMapping("testReadOneVar")
    public R testReadOneVar() throws Exception {
        System.out.println("uaService.hashCode(): "+uaService.hashCode());

        DataValue dataValue = uaService.getValue(PLCVar.INT32_3,"plc1");
        return R.ok().put("result",dataValue.getValue().getValue());
    }

    @GetMapping("testReadTwoVar")
    public R testReadTwoVar() throws Exception {
        System.out.println("uaService.hashCode(): "+uaService.hashCode());

        List<PLCVar> list = new ArrayList<>();
        list.add(PLCVar.Boolean_3);
        list.add(PLCVar.INT32_3);

        List<DataValue> values = uaService.getValues(list ,"plc1");
        List<Object> res = new ArrayList<>();
        for(DataValue dv:values){
            res.add(dv.getValue().getValue());
        }
        return R.ok().put("result",res);
    }

    @GetMapping("subscribeInt32")
    public R subscribeInt32() throws Exception {
        //只要这个线程还在执行 就会一直未true。
        boolean alive = PLCConstant.displayThread.isAlive();

        uaService.subscribe(PLCVar.INT32_3,new Double(1000),(item,dataValue)->{

            System.err.println("（测试是否 每隔intervel 都会执行这个回调方法） subscription value received: item:NodeId : " +
                    ""+item.getReadValueId().getNodeId()+", value :"+ dataValue.getValue());
            System.out.println();

            Object value = dataValue.getValue().getValue();
            try {
                webSocketServer.sendtoAll(value.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
            if(value.equals(11)){
                System.err.println("subscribeInt32  I am over");
            }
        },"plc2",1);
        return R.ok().put("result","ok");
    }

    @GetMapping("subscribeByte")
    public R subscribeByte() throws Exception {
        //只要这个线程还在执行 就会一直未true。
        boolean alive = PLCConstant.displayThread.isAlive();

        uaService.subscribe(PLCVar.BYTE_3,new Double(1000),(item,dataValue)->{

            System.err.println("（测试是否 每隔intervel 都会执行这个回调方法） subscription value received: item:NodeId : " +
                    ""+item.getReadValueId().getNodeId()+", value :"+ dataValue.getValue());
            System.out.println();

            Object value = dataValue.getValue().getValue();
            //CommonFunction.judgeVarType(value);
            //System.out.println(integer);

            try {
                webSocketServer.sendtoAll(value.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
            if(value.equals(11)){
                System.err.println("subscribeInt32  I am over");
            }
        },"plc1",1);
        return R.ok().put("result","ok");
    }

    @GetMapping("suspendSubscribeInt32")
    public R suspendSubscribeInt32() throws Exception {
        final AtomicInteger eventCount = new AtomicInteger(0);
        List<Integer> namespace = new ArrayList<>();
        namespace.add(3);
        List<Object> identify = new ArrayList<>();
        identify.add("Int32");
        return R.ok().put("result",uaService.suspendSubscribe("plc2",namespace,identify));
    }

    @GetMapping("delSubscribeInt32")
    public R delSubscribeInt32() throws Exception {
        //只要这个线程还在执行 就会一直未true。
        boolean alive = PLCConstant.displayThread.isAlive();
        List<Integer> ns = new ArrayList<>();
        ns.add(PLCVar.INT32_3.getNameSpace());

        List<Object> id = new ArrayList<>();
        id.add(PLCVar.INT32_3.getIdentifier());
        uaService.deleteSubscribe("plc2",ns,id);
        return R.ok().put("result","ok");
    }

    @GetMapping("subscribeCounter1")
    public R subscribeCounter1() throws Exception {

        uaService.subscribe(PLCVar.Counter1_5,new Double(1000),(item,dataValue)->{

            System.err.println("（测试是否 每隔intervel 都会执行这个回调方法） subscription value received: item:NodeId : " +
                    ""+item.getReadValueId().getNodeId()+", value :"+ dataValue.getValue());
            System.out.println();

            Object value = dataValue.getValue().getValue();
            try {
                webSocketServer.sendtoAll(value.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
            if(value.equals(11)){
                System.err.println("subscribeInt32  I am over");
            }
        },"plc1",1);
        return R.ok().put("result","ok");
    }

    @GetMapping("subscribeBoolen")
    public R subscribeBoolen() throws Exception {
        uaService.subscribe(PLCVar.Boolean_3,new Double(1000),(item,dataValue)->{

            System.err.println("（测试是否 每隔intervel 都会执行这个回调方法） subscription value received: item:NodeId : " +
                    ""+item.getReadValueId().getNodeId()+", value :"+ dataValue.getValue());
            System.out.println();
            Object value = dataValue.getValue().getValue();
            //Integer integer = CommonFunction.judgeVarType(value);
            //System.out.println(integer);

            try {
                webSocketServer.sendtoAll(value.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
            if(value.equals(false)){
                System.err.println("subscribeBoolen  I am over");
            }
        },"plc1",1);
        return R.ok().put("result","ok");
    }

    @GetMapping("subscribeMultiply")
    public R subscribeMultiply() throws Exception {
        List<PLCVar> list = new ArrayList<>();
        list.add(PLCVar.Boolean_3);
        list.add(PLCVar.INT32_3);

        uaService.subscribeValues(list,new Double(1000),(item,dataValue)->{

            System.err.println("（测试是否 每隔intervel 都会执行这个回调方法） subscription value received: item:NodeId : " +
                    ""+item.getReadValueId().getNodeId()+", value :"+ dataValue.getValue());
            System.out.println();
            Object value = dataValue.getValue().getValue();
            try {
                webSocketServer.sendtoAll(value.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
            if(value.equals(11)){
                System.err.println("subscribeInt32  I am over");
            }
        },"plc1");
        return R.ok().put("result","ok");
    }

    @GetMapping("subscribeEvent")
    public R subscribeEvent() throws Exception {
        final AtomicInteger eventCount = new AtomicInteger(0);

        Integer a = uaService.subscribeEvent("plc1",0,2253,((uaMonitoredItem, variants) -> {
            logger.info("Event Received from {}",uaMonitoredItem.getReadValueId().getNodeId());

            //这里variants 就是 0,2253 这个事件的 变量
            for (int i = 0; i < variants.length; i++) {
                logger.info("\t variant[{}]: {}", i, variants[i].getValue());
            }

            if (eventCount.incrementAndGet() == 3) {
                //如果收到这个事件 3次以后 就可以退出了。
            }
        }));
        return R.ok().put("result",a);
    }

    @GetMapping("subscribeEvent2")
    public R subscribeEvent2() throws Exception {
        final AtomicInteger eventCount = new AtomicInteger(0);
        uaService.subscribeEvent("plc1",2,"MyDevice",((uaMonitoredItem, variants) -> {
            logger.info("Event Received from {}",uaMonitoredItem.getReadValueId().getNodeId());
            //这里variants 就是 0,2253 这个事件的 变量
            for (int i = 0; i < variants.length; i++) {
                logger.info("\t variant[{}]: {}", i, variants[i].getValue());
            }

            if (eventCount.incrementAndGet() == 3) {
                //如果收到这个事件 3次以后 就可以退出了。
            }
        }));
        return R.ok().put("result","ok");
    }

    @GetMapping("subscribeEvents")
    public R subscribeEvents() throws Exception {
        final AtomicInteger eventCount = new AtomicInteger(0);
        List<Integer> nameSpace = new ArrayList<>();
        List<Object> identifier = new ArrayList<>();
        nameSpace.add(0);
        identifier.add(2253);
        nameSpace.add(2);
        identifier.add("MyDevice");

        BiConsumer<UaMonitoredItem, Variant[]> a1 =((uaMonitoredItem, variants) -> {
            logger.info("Server Event Received from {}", uaMonitoredItem.getReadValueId().getNodeId());
            //这里variants 就是 0,2253 这个事件的 变量
            for (int i = 0; i < variants.length; i++) {
                logger.info("\t variant[{}]: {}", i, variants[i].getValue());
            }

            if (eventCount.incrementAndGet() == 3) {
                //如果收到这个事件 3次以后 就可以退出了。

            }
        });
        
        BiConsumer<UaMonitoredItem, Variant[]> a2 =((uaMonitoredItem, variants) -> {
            logger.info("myDevice Event Received from {}", uaMonitoredItem.getReadValueId().getNodeId());
            //这里variants 就是 0,2253 这个事件的 变量
            for (int i = 0; i < variants.length; i++) {
                logger.info("\t variant[{}]: {}", i, variants[i].getValue());
            }

            if (eventCount.incrementAndGet() == 3) {
                //如果收到这个事件 3次以后 就可以退出了。
            }
        });
        List<BiConsumer<UaMonitoredItem, Variant[]>> list = new ArrayList<>();
        list.add(a1);
        list.add(a2);

        Integer plc1 = uaService.subscribeEvents("plc1", nameSpace, identifier,list);
        return R.ok().put("result",plc1);
    }

    @GetMapping("suspendSubscribeEvent")
    public R suspendSubscribeEvent() throws Exception {
        final AtomicInteger eventCount = new AtomicInteger(0);
        List<Integer> namespace = new ArrayList<>();
        namespace.add(0);
        List<Object> identify = new ArrayList<>();
        identify.add(2253);
        return R.ok().put("result",uaService.suspendSubscribe("plc1",namespace,identify));
    }

    @GetMapping("suspendSubscribeEvent2")
    public R suspendSubscribeEvent2() throws Exception {
        final AtomicInteger eventCount = new AtomicInteger(0);
        List<Integer> namespace = new ArrayList<>();
        namespace.add(2);
        List<Object> identify = new ArrayList<>();
        identify.add("MyDevice");
        return R.ok().put("result",uaService.suspendSubscribe("plc1",namespace,identify));
    }

    @GetMapping("suspendSubscribeEvents")
    public R suspendSubscribeEvents() throws Exception {
        final AtomicInteger eventCount = new AtomicInteger(0);
        List<Integer> namespace = new ArrayList<>();
        List<Object> identify = new ArrayList<>();
        namespace.add(0);
        identify.add(2253);
        namespace.add(2);
        identify.add("MyDevice");

        return R.ok().put("result",uaService.suspendSubscribe("plc1",namespace,identify));
    }



    @GetMapping("suspendSubscribeVar2")
    public R suspendSubscribeVar2() throws Exception {
        final AtomicInteger eventCount = new AtomicInteger(0);
        List<Integer> namespace = new ArrayList<>();
        namespace.add(3);
        List<Object> identify = new ArrayList<>();
        identify.add("Boolean");
        return R.ok().put("result",uaService.suspendSubscribe("plc1",namespace,identify));
    }

    @GetMapping("suspendSubscribeVars")
    public R suspendSubscribeVars() throws Exception {
        final AtomicInteger eventCount = new AtomicInteger(0);
        List<Integer> namespace = new ArrayList<>();
        namespace.add(3);
        namespace.add(3);

        List<Object> identify = new ArrayList<>();
        identify.add("Boolean");
        identify.add("Int32");

        return R.ok().put("result",uaService.suspendSubscribe("plc1",namespace,identify));
    }


    //test Real PLC
    @GetMapping("testWriteREALPlc")
    public R testWriteREALPlc(Integer a) throws Exception {

        System.out.println("uaService.hashCode(): "+uaService.hashCode());
        Boolean aBoolean = null;
        try {
            aBoolean = uaService.setValue(PLCVar.RealPLC, Unsigned.ubyte(a),"plc3");

        }catch (Exception e){
            String[] errMsgs = e.getMessage().split(",");
            for(String i : errMsgs){
                System.out.println("i = 》 " + i);
            }
            System.err.println("err msg: "+uaService.extractError(e.getMessage()));
        }

        return R.ok().put("result",aBoolean);
    }
    @GetMapping("testWriteREALPlc2")
    public R testWriteREALPlc2(Integer a) throws Exception {

        System.out.println("uaService.hashCode(): "+uaService.hashCode());
        Boolean aBoolean = null;
        try {
            aBoolean = uaService.setValue(PLCVar.RealPLC, a,"plc3");
        }catch (Exception e){
            String[] errMsgs = e.getMessage().split(",");
            for(String i : errMsgs){
                System.out.println("i = 》 " + i);
            }
            System.err.println("err msg: "+uaService.extractError(e.getMessage()));
        }

        return R.ok().put("result",aBoolean);
    }


    @GetMapping("testReadREALPlc")
    public R testReadREALPlc() throws Exception {
        System.out.println("uaService.hashCode(): "+uaService.hashCode());
        DataValue dataValue = uaService.getValue(PLCVar.RealPLC,"plc3");
        return R.ok().put("result",CommonFunction.var(dataValue.getValue().getValue()));
    }

    @GetMapping("testReadREALPlc3")
    public R testReadREALPlc3() throws Exception {
        System.out.println("uaService.hashCode(): "+uaService.hashCode());

        DataValue dataValue = uaService.getInitialNode(2255,"plc3");
        Object b = dataValue.getValue().getValue();
        return R.ok().put("result",CommonFunction.var(b));
    }

    @GetMapping("testReadREALPlc3Brow")
    public R testReadREALPlc3Brow() throws Exception {
        System.out.println("uaService.hashCode(): "+uaService.hashCode());
        NodeIdKey nodeIdKey = uaService.browseA("plc3", 3, "@LOCALSERVER");
        return R.ok().put("result",nodeIdKey);
    }

    //todo main
    @GetMapping("testWriteArray")
    public R testWriteArray() throws Exception {
        System.out.println("uaService.hashCode(): "+uaService.hashCode());
        String newValue = "false,false,false,false,false#QBoolean";

        Object[] objects = PLCType.QArray.convertArray(newValue);

        //Boolean aBoolean = uaService.setValue(3, "BooleanArray", o, "plc1");

        //todo
        //uaService.setValues()
        return R.ok().put("result",123);
    }
    @GetMapping("testWriteByteArray")
    public R testWriteByteArray() throws Exception {
        System.out.println("uaService.hashCode(): "+uaService.hashCode());
        String newValue = "6.1,6.1,6.1,6.1,6.1#QFloat";

        //注意 这种方式也可以得到数据类型但是无法new 出 对应类型 的变量数组 如Boolen[] 只能是 Object[] 这样无法通过Milo写入OPC-SERVER
        Object objectsaa = PLCType.QArray.convertType(newValue);
        Object[] z1 = (Object[])objectsaa;
        Object z2 = z1[0];
        String name = z2.getClass().getName();

        Object[] objects = PLCType.QArray.convertArray(newValue);

        //Boolean aBoolean = uaService.setValue(3, "BooleanArray", o, "plc1");
        //ns=3;s=ByteArray  ns=3;s=FloatArray

        DataValue aByte = uaService.getValue(3, "FloatArray","plc1");

        //todo 可以通过下面这种方式取到对应的数据类型，并且 解析出 数据里面的数据类型（放到judgeVarType 函数中去）
        Object os = aByte.getValue().getValue();
        Object[] osa = (Object[])os;
        Object a = osa[0];
        Object o = CommonFunction.judgeVarType(aByte.getValue().getValue());
        Object o1 = CommonFunction.judgeVarType(a);

        //todo
        //uaService.setValues()
        return R.ok().put("result",o+"|"+o1);
    }

    @GetMapping("testWriteDoubleArray")
    public R testWriteDoubleArray() throws Exception {
        System.out.println("uaService.hashCode(): "+uaService.hashCode());
        String newValue = "7.1,7.1,7.1,7.1,7.1#QDouble";


        Object[] objects = PLCType.QArray.convertArray(newValue);

        //ns=3;s=DoubleArray

        DataValue aByte = uaService.getValue(3, "DoubleArray","plc1");
        Object o = CommonFunction.judgeVarType(aByte.getValue().getValue());
        System.err.println("before:"+o);

        Boolean aBoolean = uaService.setValue(3, "DoubleArray", objects, "plc1");
        System.err.println("是否写成功"+aBoolean);

        DataValue aByte1 = uaService.getValue(3, "DoubleArray","plc1");
        Object o1 = CommonFunction.judgeVarType(aByte1.getValue().getValue());
        System.err.println("before:"+o1);

        //todo
        //uaService.setValues()
        return R.ok().put("result",o+"|"+o1);
    }

    @GetMapping("getByteArrayValue")
    public R getByteArrayValue() throws Exception {
        System.out.println("uaService.hashCode(): "+uaService.hashCode());
        //ns=3;s=ByteArray
        DataValue value = uaService.getValue(3, "BooleanArray", "plc1");
        //todo
        return R.ok().put("result",value.getValue().getValue());
    }

    @GetMapping("subscribeRealPLCVar")
    public R subscribeRealPLCVar() throws Exception {
        //只要这个线程还在执行 就会一直未true。
        boolean alive = PLCConstant.displayThread.isAlive();

        uaService.subscribe(PLCVar.RealPLC,new Double(1000),(item,dataValue)->{

            System.err.println("（测试是否 每隔intervel 都会执行这个回调方法） subscription value received: item:NodeId : " +
                    ""+item.getReadValueId().getNodeId()+", value :"+ dataValue.getValue());
            System.out.println();

            Object value = dataValue.getValue().getValue();
            IdType types = dataValue.getValue().getDataType().get().getType();
            int typeValue = dataValue.getValue().getDataType().get().getType().getValue();
            //Integer integer = CommonFunction.judgeVarType(value);

            try {
                webSocketServer.sendtoAll(value.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
            if(value.equals(11)){
                System.err.println("subscribeInt32  I am over");
            }
        },"plc3",1);
        return R.ok().put("result","ok");
    }

    @GetMapping("subscribeList")
    public R subscribeList() throws Exception {
        //只要这个线程还在执行 就会一直未true。
        boolean alive = PLCConstant.displayThread.isAlive();

        uaService.subscribe(PLCVar.StringArray_3,new Double(1000),(item,dataValue)->{

            System.err.println("（测试是否 每隔intervel 都会执行这个回调方法） subscription value received: item:NodeId : " +
                    ""+item.getReadValueId().getNodeId()+", value :"+ dataValue.getValue());
            System.out.println();

            Object value = dataValue.getValue().getValue();

            IdType types = dataValue.getValue().getDataType().get().getType();
            System.out.println("types:"+types);
            int typeValue = dataValue.getValue().getDataType().get().getType().getValue();
            System.out.println("typeValue:"+typeValue);
            //Integer integer = CommonFunction.judgeVarType(value);
            //System.out.println("integer:"+integer);

            try {
                webSocketServer.sendtoAll(value.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
            if(value.equals(11)){
                System.err.println("subscribeInt32  I am over");
            }
        },"plc1",1);
        return R.ok().put("result","ok");
    }
*/

}
